除了 Query 和 Mutation ,GraphQL 還提供第三種類型 Subscription。
Subscription 是一種將資料由 server 推向 clinet 的一種方式,而不是 clinet 發送請求後 server 回傳資料。
將 installSubscriptionHandlers 設定為 true
GraphQLModule.forRoot({
  installSubscriptionHandlers: true,
})
NestJs Graphql 提供了 @Subscription decorator ,我們會將要使用此類型的函式加上 decorator
接著使用 graphql-subscriptions package 的 PubSub ,提供簡單的 publish(發布) 以及 subscribe(訂閱) 事件 API
調用 PubSub#asyncIterator 來訂閱事件。
事件名稱:commentAdded
我們有兩種方式可以定義事件方法:
//Path: src/authors/authors.resolver.ts
import { Resolver, Query, ID, Args, Subscription, Mutation } from "@nestjs/graphql";
import { PubSub } from 'graphql-subscriptions';
import { AuthorsService } from './authors.service';
import { Author } from './models/author.model';
import { Comment } from './models/comment.model';
const pubSub = new PubSub();
@Resolver(of => Author)
export class AuthorsResolver {
    ...
    // 方法一
    // @Subscription(returns => Comment)
    // commentAdded() {
    //     return pubSub.asyncIterator('commentAdded');
    // }
    // 方法二
    @Subscription(returns => Comment, {
        name: 'commentAdded',
    })
    addCommentHandler() {
        return pubSub.asyncIterator('commentAdded');
    }
}
// Path: src/authors/models/comment.model.ts
@ObjectType()
export class Comment {
    @Field({ nullable: true })
    comment?: string;
}
調用 PubSub#publish 來發佈事件
type Subscription {
  commentAdded: Comment!
}
import { Resolver, Query, ID, Args, Subscription, Mutation } from "@nestjs/graphql";
import { PubSub } from 'graphql-subscriptions';
import { AuthorsService } from './authors.service';
import { Author } from './models/author.model';
import { Comment } from './models/comment.model';
const pubSub = new PubSub();
@Resolver(of => Author)
export class AuthorsResolver {
    ...
    @Mutation(returns => Comment) 
    addComment(@Args('comment', { type: () => String}) comment: string) {
        pubSub.publish('commentAdded',  { commentAdded: { comment } });
        return { comment };
    }
    ...
}
啟動服務,打開 Playground 進行測試
addComment API 發布事件
subscription 監聽事件
mutation {
  addComment(comment: "comment") {
    comment
  }
}
subscription {
  commentAdded {
    comment
  }
}
先讓 Subscription 進行監聽
在未收到事件之前,它會一直轉圈圈,這很正常
執行 Mutation addComment
回到 Subscription commentAdded,能看到我們成功接收到事件的回傳值
可以多發幾次事件請求,就能看到事件會一直往下增長
對,他是往下,而且不能 scroll !!
想要過濾掉特定事件,可以使用 filter 屬性,它有兩個參數 payload, variables,最後回傳一個 boolean 值,決定是否會將事件發佈給前端監聽器。
payload 是由事件發送者傳過來的參數
variables 是訂閱者所接收到的參數
@Subscription(returns => Comment, {
    name: 'commentAdded',
    
    // 加入 filter 以及判斷式
    filter: (payload, variables) => {
        return payload.commentAdded.title === variables.title
    }
})
// 加入訂閱者參數
addCommentHandler(@Args('title') title: string) {
    return pubSub.asyncIterator('commentAdded');
}
接著到 playground 進行測試,發布者及訂閱者都多了 title 參數,在上面的判斷是中,我們設定兩者的 title 要一樣訂閱者才能成功接收到事件
讀者可以直接測試,當設定一樣的值,就能收到事件,反之,不一樣的值,subscription 就不會有任何反應
這樣我們就成功利用過濾器,過濾我們想要的事件
| subscription | mutation | 
|---|---|
![]()  | 
![]()  | 
官方還有 Sehema first 範例說明,由於只是 Schema 產生方式不太一樣,所以我這邊就不在多做說明
以上就是 Subscription 介紹!